package com.flyqiu.form.core;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.flyqiu.common.bean.FlyQiuBeanManage;
import com.flyqiu.common.bean.FlyQiuSimpleBeanManage;
import com.flyqiu.common.tools.FlyQiuCollectionTools;
import com.flyqiu.common.transaction.FlyQiuTransactionManage;
import com.flyqiu.common.transaction.SimpleTransactionManage;
import com.flyqiu.form.api.FlyQiuFormContext;
import com.flyqiu.form.api.col.FlyQiuStoreColTypeManage;
import com.flyqiu.form.api.event.FlyQiuTableDataEventManage;
import com.flyqiu.form.api.event.FlyQiuTableEventManage;
import com.flyqiu.form.api.rule.FlyQiuDataRuleManage;
import com.flyqiu.form.api.service.FlyQiuTableConfigService;
import com.flyqiu.form.api.spi.FlyQiuFormStoreInitialization;
import com.flyqiu.form.api.store.FlyQiuAvueDynamicService;
import com.flyqiu.form.api.store.FlyQiuFormCoreService;
import com.flyqiu.form.api.store.FlyQiuFormStoreManage;
import com.flyqiu.form.core.col.DefaultFlyQiuStoreColTypeManage;
import com.flyqiu.form.core.event.DefaultFlyQiuDataEventManage;
import com.flyqiu.form.core.event.DefaultFlyQiuEventManage;
import com.flyqiu.form.core.rule.DefaultFlyQiuDataRuleManage;
import com.flyqiu.form.core.service.FlyQiuTableConfigServiceImpl;
import com.flyqiu.form.core.storage.DefaultFlyQiuFormStoreManage;
import com.flyqiu.form.core.storage.FlyQiuAvueDynamicServiceImpl;
import com.flyqiu.form.mapper.FlyQiuTableConfigMapper;
import lombok.Data;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.transaction.TransactionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.jdbc.support.JdbcTransactionManager;

import javax.sql.DataSource;
import java.util.List;

@Data
public class DefaultFlyQiuFormContext implements FlyQiuFormContext {
    public static final String FLY_QIU_FORM_MAPPER = FlyQiuTableConfigMapper.class.getPackage().getName();

    protected FlyQiuBeanManage beanManage;
    protected FlyQiuTransactionManage transactionManage;

    protected FlyQiuTableEventManage formEventManage;
    protected FlyQiuTableDataEventManage formDataEventManage;
    protected FlyQiuFormStoreManage formStoreManage;
    protected FlyQiuDataRuleManage flyQiuDataRuleManage;
    protected FlyQiuStoreColTypeManage storeColTypeManage;

    protected FlyQiuFormCoreService flyQiuCoreFormService;
    protected FlyQiuTableConfigService flyQiuTableConfigService;
    protected FlyQiuAvueDynamicService avueDynamicService;

    @Override
    public FlyQiuBeanManage getBeanManage() {
        return beanManage;
    }

    @Override
    public FlyQiuTransactionManage getTransactionManage() {
        return transactionManage;
    }

    @Override
    public FlyQiuTableEventManage getFormEventManage() {
        return formEventManage;
    }

    @Override
    public FlyQiuTableDataEventManage getFormDataEventManage() {
        return formDataEventManage;
    }

    @Override
    public FlyQiuTableConfigService getTableConfigService() {
        return flyQiuTableConfigService;
    }

    @Override
    public FlyQiuAvueDynamicService getAvueDynamicService() {
        return avueDynamicService;
    }

    @Override
    public FlyQiuDataRuleManage getFlyQiuDataRuleManage() {
        return flyQiuDataRuleManage;
    }

    @Override
    public FlyQiuStoreColTypeManage getStoreColTypeManage() {
        return storeColTypeManage;
    }

    public static DefaultFlyQiuFormContext create(DataSource dataSource, TransactionFactory transactionFactory, List<FlyQiuFormStoreInitialization> storeInitializations) {
        //初始化全局上下文
        DefaultFlyQiuFormContext context = new DefaultFlyQiuFormContext();
        //创建表事件管理
        context.formEventManage = new DefaultFlyQiuEventManage();
        //创建表数据事件管理
        context.formDataEventManage = new DefaultFlyQiuDataEventManage();

        //创建sqlSession
        SqlSessionTemplate sqlSession = createSqlSessionTemplate(dataSource, transactionFactory, storeInitializations);
        //创建事务管理
        context.transactionManage = createTransactionManage(dataSource);

        //bean对象管理器
        context.beanManage = new FlyQiuSimpleBeanManage(sqlSession);
        //存储管理器
        context.formStoreManage = new DefaultFlyQiuFormStoreManage();
        //数据规则管理器
        context.flyQiuDataRuleManage = new DefaultFlyQiuDataRuleManage();
        //存储列类型管理器
        context.storeColTypeManage = new DefaultFlyQiuStoreColTypeManage();

        FlyQiuTableConfigMapper mapper = context.beanManage.getMapper(FlyQiuTableConfigMapper.class);
        //数据表配置服务
        context.flyQiuTableConfigService = new FlyQiuTableConfigServiceImpl(mapper);
        //动态子表单服务
        context.avueDynamicService = new FlyQiuAvueDynamicServiceImpl(context.formStoreManage, context.flyQiuTableConfigService);
        //表单核心服务
        context.flyQiuCoreFormService = new FlyQiuFormCoreServiceImpl(context.flyQiuTableConfigService, context.getFormStoreManage());

        return context;
    }

    /**
     * 创建事务管理器
     *
     * @param dataSource 数据源
     * @return {@link SimpleTransactionManage}
     */
    public static SimpleTransactionManage createTransactionManage(DataSource dataSource) {
        JdbcTransactionManager transactionManager = new JdbcTransactionManager(dataSource);
        return new SimpleTransactionManage(transactionManager);
    }

    public static SqlSessionTemplate createSqlSessionTemplate(DataSource dataSource, TransactionFactory transactionFactory, List<FlyQiuFormStoreInitialization> storeInitializations) {
        Environment environment = new Environment("flyQiuFormEngine", transactionFactory, dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration(environment);
        configuration.addMappers(FLY_QIU_FORM_MAPPER);
        FlyQiuCollectionTools.iterator(storeInitializations, (store) -> store.initMapper(configuration));
        MybatisSqlSessionFactoryBuilder mybatisSqlSessionFactoryBuilder = new MybatisSqlSessionFactoryBuilder();
        GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
        globalConfig.setSqlInjector(new DefaultSqlInjector());        //此参数会自动生成实现baseMapper的基础方法映射
        globalConfig.setIdentifierGenerator(DefaultIdentifierGenerator.getInstance());      //设置id生成器
        globalConfig.setSuperMapperClass(BaseMapper.class);  //设置超类mapper
        configuration.setLogImpl(StdOutImpl.class);
        SqlSessionFactory build = mybatisSqlSessionFactoryBuilder.build(configuration);
        return new SqlSessionTemplate(build);
    }

}
